<template>
  <!-- 使用 Icon 图标组件，通过设置样式，让左侧箭头显示在顶部导航栏指定位置 -->
  <van-icon name="arrow-left" class="left-arrow" @click="onClickLeft"/>
  <!--
    Tab 标签页组件设置导航标签切换，和标签对应的内容区域
    color 设置文字下方横线的主体色；
    scrollspy 是否开启滚动导航，默认值为 false，开启滚动模式内容将会垂直方向平铺展示，点击 title 滚动指定内容区域；
    sticky 属性可以开启粘性布局，粘性布局下，标签页滚动到顶部时会自动吸顶；
    浏览器中类名为 van-tabs__wrap 地方是切换的标签，title 是设置顶部导航的切换标签；
    浏览器中类名为van-tabs__content 是对应的内容区域，van-tab 标签内部设置标签对应的内容；
  -->
  <van-tabs color="#FBC546" scrollspy sticky>
    <!---------------- 商品信息 ------------------>
    <van-tab title="商品" class="productInfo">
      <!-- 1. 轮播图 -->
      <van-swipe class="my-swipe" :autoplay="3000" height="375">
        <van-swipe-item v-for="(item, index) in swipeInfo" :key="index">
          <img :src="item" alt="">
        </van-swipe-item>
      </van-swipe>
      <!-- 2. 商品的价格标题销量
        van-cell 组件使用插槽自定义单元格中的内容
        title 属性设置的是文字内容，左侧对齐；
        使用 right-icon 插槽来自定义右侧图标；
        Cell 可以单独使用，也可以与 CellGroup 搭配使用，CellGroup 可以为 Cell 提供上下外边框。
        van-cell-group 设置 :border="false" 不显示外边框；
        van-cell 设置 :border="false" 不显示内边框；
      -->
      <van-cell-group :border="false">
        <van-cell class="price" :border="false">
          <template #title>
            <span>￥{{ storeInfo?.price || 0 }}</span>
          </template>
        <template #right-icon>
          <van-icon name="share-o" />
        </template>
        </van-cell>
        <van-cell class="desc" :border="false">
          <template #title>
            <p v-text="storeInfo?.store_name"></p>
          </template>
        </van-cell>
        <van-cell class="sales" :border="false">
          <template #title>
            <!-- storeInfo?.stock 因为数据需要请求后获取，第一次可能获取不到，所以后面加上 ? 可以避免这样 的报错，storeInfo?.unit_name 单位 -->
            <span>原价：￥{{ storeInfo?.ot_price  || 0 }}</span>
            <span>库存：{{ (storeInfo?.stock || 0)  + ' ' + (storeInfo?.unit_name || '') }}</span>
            <span>销量：{{ (storeInfo?.fsales || 0)  + ' ' + (storeInfo?.unit_name || '') }}</span>
          </template>
        </van-cell>
      </van-cell-group>
      <!-- 3. 商品规格选择区域，设置 is-link 属性后会在单元格右侧显示箭头 -->
      <van-cell is-link class="sku_window" @click="showPopup">
        <template #title>
          已选择：{{ sku }}
        </template>
      </van-cell>
      <!-- 商品规格弹出层， position="bottom" 从底部弹出 -->
      <van-popup
        v-model:show="specState.show"
        position="bottom"
      >
        <van-cell-group :border="false">
          <!-- 1. 商品头部信息 -->
          <van-cell class="popup-header">
          <van-card
           :price="skuProduct?.price"
           :title="storeInfo?.store_name"
           :thumb="skuProduct?.image"
          >
          <!-- 商品库存 -->
           <template #num>
             库存：{{ (skuProduct?.stock || 0)  + ' ' + (storeInfo?.unit_name || '') }}
           </template>
          </van-card>
          </van-cell>
          <!-- 2. 商品规格信息 -->
          <!-- 遍历得到每一个规格 -->
          <van-cell class="popup-spec" v-for="(tag, tagIndex) in productAllSpec" :key="tagIndex">
            <p v-text="tag.attr_name"></p>
            <!-- 遍历获取当前规格的每一个属性
              specState.spec 存储着被选中规格的某个属性的集合 {0: '亮黑色', 1: '8GB+128GB', 2: '标准版'}
              specState.spec[tagIndex] === attr 当前规格中的属性只要与 specState.spec 存储的对应属性相等，active 类就生效
            -->
            <span
              class="tag"
              v-for="(attr, attrIndex) in tag.attr_values"
              :class="{active: specState.spec[tagIndex] === attr}"
              :key="attrIndex"
              v-text="attr"
              @click="selectAttr(attr, tagIndex)"
            >
            </span>
          </van-cell>
          <!-- 3. 商品购买数量, max 绑定库存量 -->
          <van-cell class="popup-num" title="数量">
            <van-stepper v-model="specState.buyNum" :max="skuProduct?.stock || 0" />
          </van-cell>
        </van-cell-group>
        <!-- 商品确认加入到购物车按钮 -->
        <van-action-bar-button type="danger" text="确定加入" @click="addCart()"/>
      </van-popup>
    </van-tab>
    <!---------------- 用户评价 ------------------>
    <van-tab title="评价" class="comment">
      <!-- 1. 总体评价 -->
      <van-cell
        :title="replyCount"
        is-link :value="replyChance"
        class="overall"
        :to="{
          name: 'comment',
          params: {
            productId
          }
        }"
      />
      <!--
        2. 引入 CommentItem 组件，展示单条用户评论信息；
        将用户评论数组传递给 CommentItem 组件；
        使用 v-if 判断评论数是否为 0，并且是否已经获取到用户评价信息，控制 CommentItem 组件的显示隐藏；
      -->
     <CommentItem :user-reply="userReply" v-if="replyCount !== 0 && isReply"/>
    </van-tab>
    <!---------------- 推荐商品 ------------------>
    <van-tab title="推荐" class="recommend">
      <p class="recommend-title">推荐商品</p>
      <van-grid :gutter="10" :column-num="3" :border="false">
        <van-grid-item
          v-for="item in goodList"
          :key="item.id"
          :to="{
            name: 'product',
            params: {
              productId: item.id
            }
          }"
          >
          <van-image
            :src="item.image"
          />
          <p v-text="item.store_name"></p>
          <span>￥{{ item.price }}</span>
        </van-grid-item>
      </van-grid>
    </van-tab>
    <!---------------- 商品详情 ------------------>
    <van-tab title="详情">
      <div class="description" v-html="storeInfo?.description"></div>
    </van-tab>
  </van-tabs>
  <!-- 购物车和立即购买的固定底部栏，设置购物车的路由跳转为 /cart -->
  <van-action-bar>
    <van-action-bar-icon icon="chat-o" text="客服" color="#ee0a24" />
    <van-action-bar-icon icon="cart-o" text="购物车" to="/cart"/>
    <van-action-bar-icon icon="star" text="已收藏" color="#ff5000" />
    <van-action-bar-button type="warning" text="加入购物车" @click="showSku()"/>
    <van-action-bar-button type="danger" text="立即购买" />
  </van-action-bar>

</template>
<script setup>
import CommentItem from '@/components/CommentItem.vue'
import { ref, computed, reactive } from 'vue'
import { showToast } from 'vant'
import { onBeforeRouteUpdate, useRouter } from 'vue-router'
import { getProductDetails } from '@/api/products.js'
import { addToCart } from '@/api/cart.js'
import useStore from '@/store/index.js'
// 创建 router 实例，利用 router.push 实现路由跳转
const router = useRouter()
/* ------------ 获取商品详情的所有信息 ------------- */
// 1. 接收父组件传递来的商品 id
const { productId } = defineProps({
  productId: {
    type: String,
    require: true
  }
})
// 2. 声明响应式变量，存储商品详情信息
const productDetails = ref({})
// 3. 根据商品 id 发送获取商品详情的请求
const initProductDetails = async (productId) => {
  const { data } = await getProductDetails(productId)
  if (data.status !== 200) {
    // 商品 id 错误，找不到商品，跳回首页
    router.push({
      name: 'home'
    })
    return
  }
  console.log(data)
  productDetails.value = data.data
  // 获取到响应数据后，执行初始化规格函数，默认选中规格中的第一个属性
  initSpec(data.data.productAttr)
}
initProductDetails(productId)

// 点击左侧返回按钮，页面跳转到上一级页面
const onClickLeft = () => history.back()

/* ---------------- 通过计算属性获取所需数据 ----------------- */
// 1. 声明变量，存储商品信息
const storeInfo = computed(() => productDetails.value.storeInfo)
// 1.1. 声明变量，存储轮播图图片信息，因为 storeInfo.value 第一次可能获取不到，所以在后面加 ? 可以避免这个问题
const swipeInfo = computed(() => storeInfo.value?.slider_image)
// 2. 用户评价信息
// 2.1 评价数量，productDetails.value.replyCount 页面第一次可能加载不到，通过加 || 0，可以避免显示 undefined
const replyCount = computed(() => '用户评价(' + (productDetails.value.replyCount || 0) + ')')
// 2.2 好评率
const replyChance = computed(() => (productDetails.value.replyChance || 0) + '%好评率')
// 2.3 用户最新一条的评价信息
const userReply = computed(() => {
  return productDetails.value.reply
})
// 2.4 判断当前组件是否已经获取到了评价信息，只有获取到评价信息才能渲染子组件 CommentItem，避免了子组件获取不到父组件传递过来的值
const isReply = computed(() => {
  if (productDetails.value.reply) {
    return true
  }
  return false
})
// 3. 商品推荐数据
const goodList = computed(() => productDetails.value.good_list)

/* ---------------- 推荐商品路由跳转 ----------------- */
// 对于一个带有动态参数的路径 `/users/:id`，在 `/users/1` 和 `/users/2` 之间跳转的时，该组件 users 被复用时调用，但是数据没有变化，因此需要使用导航守卫 onBeforeRouteUpdate 判断路由是否改变，改变后重新加载数据
onBeforeRouteUpdate((to, from) => {
  // to 目标路由，form 跳转之前的路由
  // 清空旧的数据
  productDetails.value = {}
  // 回到页面顶部
  document.body.scrollTop = 0
  document.documentElement.scrollTop = 0
  // 重新根据最新的商品 id 请求商品数据
  initProductDetails(to.params.productId)
})

/* ------------------ 商品规格弹出层 ------------------- */
// 1. 声明响应式变量
// 1.1 弹出层的显示隐藏、被选中的规格数据、购买的商品数量，为了后续提交商品订单时使用
const specState = reactive({
  show: false, // 弹出层的显示状态
  spec: [], // 选中的规格数据
  buyNum: 0 // 购买的商品数量
})
// 1.2 商品的规格的所有数据，是一个数组
const productAllSpec = computed(() => productDetails.value.productAttr)
// 1.3 存储了所有规格搭配的商品信息
const productValue = computed(() => productDetails.value.productValue)
// 1.4 sku，被选中规格属性搭配之后的商品参数
const sku = computed(() => specState.spec.toString())
// 1.5 更具不同的 sku，获取对应的商品信息，productValue.value 属于二级计算属性，所以需要加 ? 处理
const skuProduct = computed(() => productValue.value?.[sku.value])

// 2. 控制弹出层展示的函数
const showPopup = () => {
  specState.show = true
}
// 3. 初始化规格，设置默认被选中的规格属性，参数 specs 就是当前商品的规格的所有数据
const initSpec = (specs) => {
  // 把规格的第一个属性追加 specState.spec
  specState.spec = specs.map(item => item.attr_values[0])
}
// 4. 点击时切换被选中的规格属性，currentAttr 被选中的属性值，tagIndex 存储在 specState.spec 对应的索引值
const selectAttr = (currentAttr, tagIndex) => {
  // 改变规格在 specState.spec 存储的属性，让当前属性被选中
  specState.spec[tagIndex] = currentAttr
}

/* ------------------ 购物车和立即购买的固定底部栏 ------------------- */
// 1. 创建用户状态管理实例
const { userStore } = useStore()
// 2. 点击加入购物车，判断用户是否登录，并显示商品规格弹出层
const showSku = () => {
  // 2.1 判断用户是否登录，未登录跳转到登录页面，并记录此时的商品页面路由
  if (!userStore.userToken) {
    router.push({
      name: 'login',
      query: {
        redirect: router.currentRoute.value.fullPath
      }
    })
  }
  // 2.2 用户已经登录，检测弹出层是否显示
  if (!specState.show) {
    specState.show = true
  }
}

// 3. 点击弹出层 确定加入 按钮，将商品添加到购物车
const addCart = async () => {
  // 3.1 判断用户是否登录，未登录跳转到登录页面，并记录此时的商品页面路由
  if (!userStore.userToken) {
    router.push({
      name: 'login',
      query: {
        redirect: router.currentRoute.value.fullPath
      }
    })
    return
  }
  // 3.2 发送将商品加入到购物车的请求
  const { data } = await addToCart({
    new: 0, // 提交状态，0 为加入购物车，1 为立即购买
    productId, // 商品 ID
    uniqueId: skuProduct.value.unique, // 商品规格 sku ID
    cartNum: specState.buyNum // 加入个数
  })
  if (data.status !== 200) {
    return showToast('加入购物车失败')
  }
  // 3.3 购物车商品添加成功，隐藏商品规格弹出层
  specState.show = false
  // 3.4 提示添加购物车成功
  showToast('加入购物车成功')
}
</script>
<style lang='scss' scoped>
// 左侧箭头的样式
.left-arrow {
  font-size: 20px;
  position: fixed;
  top: 13px;
  left: 12px;
  z-index: 100;
}
// 设置顶部导航标签的样式，让内容可以片中间显示一些
:deep(.van-tabs__wrap) {
  padding: 0 30px;
  background-color: #fff;
}
:deep(.van-tabs__content) {
  background-color: #f2f2f2;
  padding-bottom: var(--van-action-bar-height);
  // ---------------- 商品信息 ---------------
  .productInfo {
    // 轮播图
    .my-swipe {
      img {
        width: 100%;
      }
    }
    // 价格标题销量
    .van-cell {
      padding: 5px 10px;
    }
    .price {
      padding-top: 10px;
      span {
        font-size: 24px;
        font-weight: 700;
        display: block;
      }
      .van-icon {
        font-size: 20px;
      }
    }
    .desc {
      p {
        font-size: 16px;
        font-weight: 700;
        line-height: 1.2;
        // 设置内容最多显示两行，超出的部分用 ... 代替
        display: -webkit-box;
        -webkit-line-clamp: 2;
        overflow: hidden;
        -webkit-box-orient: vertical;
      }
    }
    .sales {
      .van-cell__title {
        display: flex;
        justify-content: space-between;
        span {
        font-size: 12px;
        color: #82848F;
        }
      }
    }
    // 商品规格
    .sku_window {
      margin: 10px 0;
    }
  }
  // ---------------- 用户评价 ---------------
  .comment {
    .van-cell {
      padding: 10px;
    }
    .overall {
      border-bottom: 1px solid #82848F;
    }
  }
  // ---------------- 推荐商品 ---------------
  .recommend {
    background-color: #fff;
    padding: 15px 10px 10px;
    .recommend-title {
      font-size: 16px;
      font-weight: 700;
      margin-bottom: 10px;
    }
    .van-grid {
      padding-left: 0!important;
      .van-grid-item__content {
        padding: 0;
        p {
          font-size: 12px;
          font-weight: 700;
          line-height: 1.2;
          margin: 5px 0;
          // 设置内容最多显示两行，超出的部分用 ... 代替
          display: -webkit-box;
          -webkit-line-clamp: 2;
          overflow: hidden;
          -webkit-box-orient: vertical;
        }
        span {
          font-size: 12px;
          color: #F2270C;
          font-weight: 700;
          // 设置 flex 属性可以单独让元素左对齐，也可以给 grid 设置 center="false" 会让所有元素左对齐
          align-self: flex-start;
        }
      }
    }
  }
  // ---------------- 商品详情 ---------------
  .description {
    width: 100%;
    // 为了避免图片或者视频宽度过大，出现横向滚动条
    img, video {
      width: 100%;
    }
  }
  // ---------------- 商品规格弹出层 ---------------
  .van-popup {
    border-radius: 10px 10px 0 0;
    max-height: 70%;
    margin-bottom: var(--van-action-bar-height);
    padding-bottom: 8px;
    .van-cell {
      padding: var(--van-cell-vertical-padding) var(--van-cell-horizontal-padding);
      .van-cell__value {
        text-align: left;
      }
    }
    // 1. 头部商品样式
    .popup-header {
      .van-cell__value {
        .van-card {
          padding: 0;
          background-color: transparent;
          .van-card__content {
            justify-content: space-around;
            .van-card__title {
              font-size: 14px;
            }
            .van-card__bottom {
              display: flex;
              flex-direction: column;
              .van-card__price {
                color: #F2270C;
                font-size: 16px;
              }
            }
          }
        }
      }
    }
    // 2. 商品规格样式
    .popup-spec {
      padding-bottom: 10px;
      p {
        color: #000;
        margin-bottom: 3px;
      }
      .tag {
        font-size: 12px;
        line-height: 1;
        display: inline-block;
        padding: 4px 15px;
        border-radius: 10px;
        margin-right: 8px;
        margin-bottom: 4px;
        border: 1px solid #ccc;
        background-color: #f2f2f2;
      }
      .tag.active {
        border-color: #F2270C;
        color: #F2270C;
        background-color: #fcedeb;
      }
    }
    // 3. 商品库存样式
    .popup-num {
      .van-cell__value {
        text-align: right;
      }
    }
    // 4. 商品确定加入购物车按钮
    .van-button {
      width: 50%;
      margin-left: 25%;
      border-radius: 20px;
    }
  }
}

// ---------------- 购物车和立即购买的固定底部栏 ---------------
.van-action-bar {
  z-index: 10000;
}
</style>
